信息熵 条件熵 交叉熵 联合熵 相对熵 KL散度 SCE MAE 互信息(信息增益)

您所在的位置:网站首页 交叉熵公式 为什么分类用交叉熵不用Mae 信息熵 条件熵 交叉熵 联合熵 相对熵 KL散度 SCE MAE 互信息(信息增益)

信息熵 条件熵 交叉熵 联合熵 相对熵 KL散度 SCE MAE 互信息(信息增益)

2024-07-10 02:28:56| 来源: 网络整理| 查看: 265

粗略版快速总结

条件熵 H ( Q ∣ P ) = 联合熵 H ( P , Q ) − H ( P ) 条件熵H(Q∣P)=联合熵H(P,Q)−H(P) 条件熵H(Q∣P)=联合熵H(P,Q)−H(P)

信息增益 I ( P , Q ) = H ( P ) − H ( P ∣ Q ) = H ( P ) + H ( Q ) − H ( P , Q ) 信息增益 I(P,Q)=H(P)−H(P∣Q)=H(P)+H(Q)-H(P,Q) 信息增益I(P,Q)=H(P)−H(P∣Q)=H(P)+H(Q)−H(P,Q),也就是Information Gain,互信息

KL散度(相对熵) K L ( P , Q ) = − H ( P ) + 交叉熵 C E ( P , Q ) KL(P,Q)=-H(P)+交叉熵CE(P,Q) KL(P,Q)=−H(P)+交叉熵CE(P,Q)

详细定义

如果一个样本是n类其中之一,也就是说target是onehot形式,例如三类那么target=[0,0,1],拿target=[0,0,1]来说就是 p 0 = 0 p_0=0 p0​=0, p 1 = 0 p_1=0 p1​=0, p 2 = 1 p_2=1 p2​=1。写成表达式可以是 p i p_i pi​,n=3 那么经过神经网络运算出来的Logits可能是在(-inf,inf)之间,那么一般会通过softmax归一化到(0,1)之间,这个归一化到(0,1)之间的数我们可以用 q i q_i qi​来表示,当然对于上面有3类的例子来说,n=3 好了,既然明确了 p i p_i pi​是第i个类的在(0,1)之间target, q i q_i qi​是第i个类的logit归一化到(0,1)之间的结果,那么开始各种定义了

相对熵(KL散度)

K L ( P , Q ) = ∑ i ∈ [ 0 , n − 1 ] p i l o g p i q i KL(P,Q)=\sum _{i \in[0,n-1]}p_i log \frac{p_i}{q_i} KL(P,Q)=i∈[0,n−1]∑​pi​logqi​pi​​

交叉熵(CE Loss)

C E ( P , Q ) = − ∑ i ∈ [ 0 , n − 1 ] p i l o g q i K L ( P , Q ) = H ( P ) + C E ( P , Q ) CE(P,Q)=-\sum _{i \in[0,n-1]}p_i log q_i \\ KL(P,Q) = H(P)+CE(P,Q) CE(P,Q)=−i∈[0,n−1]∑​pi​logqi​KL(P,Q)=H(P)+CE(P,Q) 来看一下Pytorch里的交叉熵是怎么实现的,手动验证下:

import torch from torch import nn import math loss_f = nn.CrossEntropyLoss(reduction='mean') output = torch.randn(2,3) #表示2个样本,3个类别 # target = torch.from_numpy(np.array([1, 0])).type(torch.LongTensor) target = torch.LongTensor([0,2]) #表示label0和label2 loss = loss_f(output, target) print('CrossEntropy loss: ', loss) print(f'reduction=none,所以可以看到每一个样本loss,输出为[{loss}]') def manual_cal(sample_index, target, output): #输入是样本下标 sample_output = output[sample_index] sample_target = target[sample_index] x_class = sample_output[sample_target] sample_output_len = len(sample_output) log_sigma_exp_x = math.log(sum(math.exp(sample_output[i]) for i in range(sample_output_len))) sample_loss = -x_class + log_sigma_exp_x print(f'交叉熵手动计算loss{sample_index}:{sample_loss}') return sample_loss for i in range(2): manual_cal(i, target, output) # 如果nn.CrossEntropyLoss(reduction='mean')模式,刚好是手动计算的每个样本的loss取平均,最后输出的是一个值 # 如果nn.CrossEntropyLoss(reduction='none')模式,手动计算的loss0和loss1都会被列出来

在这里插入图片描述

(class torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction=‘elementwise_mean’) 功能: 将输入经过softmax激活函数之后,再计算其与target的交叉熵损失。即该方法将nn.LogSoftmax()和 nn.NLLLoss()进行了结合。严格意义上的交叉熵损失函数应该是nn.NLLLoss()。 ​在这里插入图片描述 补充:交叉熵损失(cross-entropy Loss) 又称为对数似然损失(Log-likelihood Loss)、对数损失;二分类时还可称之为逻辑斯谛回归损失(Logistic Loss)。交叉熵损失函数表达式为 L = - sigama(y_i * log(x_i))。pytroch这里不是严格意义上的交叉熵损失函数(下面会详细解释,pytorch中交叉熵不够严格主要是因为只能接受one hot),而是先将input经过softmax激活函数,将向量“归一化”成概率形式,然后再与target计算严格意义上交叉熵损失。 在多分类任务中,经常采用softmax激活函数+交叉熵损失函数,因为交叉熵描述了两个概率分布的差异,然而神经网络输出的是向量,并不是概率分布的形式。所以需要softmax激活函数将一个向量进行“归一化”成概率分布的形式,再采用交叉熵损失函数计算loss。 再回顾PyTorch的CrossEntropyLoss(),官方文档中提到时将nn.LogSoftmax()和 nn.NLLLoss()进行了结合,nn.LogSoftmax() 相当于激活函数 , nn.NLLLoss()是损失函数; 如果用pytorch实现交叉熵可以用以下代码,顺带连rce(logits和pred互换)和sce(加权)也都实现了:

import torch.nn.functional as F import torch import torch.nn as nn class SCELoss(nn.Module): def __init__(self, num_classes=10, a=1, b=1, eps=1e-18): super(SCELoss, self).__init__() self.num_classes = num_classes self.a = a #两个超参数 self.b = b self.cross_entropy = nn.CrossEntropyLoss() self.cross_entropy_none = nn.CrossEntropyLoss(reduction="none") self.eps = eps def forward(self, raw_pred, labels): # CE 部分,正常的交叉熵损失 ce = self.cross_entropy(raw_pred, labels) # RCE pred = F.softmax(raw_pred, dim=1) pred = torch.clamp(pred, min=self.eps, max=1.0) label_one_hot = F.one_hot(labels, self.num_classes).float().to(pred.device) label_one_hot = torch.clamp(label_one_hot, min=self.eps, max=1.0) #最小设为 1e-4,即 A 取 -4 my_ce = (-1 * torch.sum(label_one_hot * torch.log(pred), dim=1)) print('pred={} label_one_hot={} my_ce={}'.format(pred, label_one_hot, my_ce)) print('raw_pred={} labels={} official_ce={}'.format(raw_pred, labels, self.cross_entropy_none(raw_pred, labels))) rce = (-1 * torch.sum(pred * torch.log(label_one_hot), dim=1)) print('pred={} label_one_hot={} rce={}'.format(pred, label_one_hot, rce)) loss = self.a * ce + self.b * rce.mean() return loss y_pred = torch.tensor([[10.0, 5.0, -6.0], [8.0, 8.0, 8.0]]) y_true = torch.tensor([0, 2]) ce1 = SCELoss(num_classes=3)(y_pred, y_true)

来感受一下交叉熵取值的妙处:当 q i q_i qi​很接近1时, − l o g q i -logq_i −logqi​很接近0,如果此时 p i p_i pi​是1,这时候整体loss会很小;当 q i q_i qi​很接近0时, − l o g q i -logq_i −logqi​很大, p i p_i pi​是1,这时候整体loss会很大。所以 p i p_i pi​就是筛选的功能,在Pytorch中CrossEntropyLoss等于LogSoftmax和NLLLoss的结合:LogSoftmax是上面公式里的 l o g ( e x p ( x [ c l a s s ] ) ∑ j e x p ( x [ j ] ) ) log(\frac{exp(x[class])}{\sum_jexp(x[j])}) log(∑j​exp(x[j])exp(x[class])​),实现了整个 l o g q i logq_i logqi​的效果;NLLLoss就是给前面加了一个负号。所以在torch中的CrossEntropy = NLLLoss(LogSoftmax) pytorch中交叉熵不够严格主要是因为只能接受one hot,也就是说torch中的target只能明确指明是哪个target,而不是上面公式 p i p_i pi​是(0,1)之间,所以在Pytorch中还保留了KLDivLoss这个loss来接受广泛的取值:

import torch.nn.functional as F import torch import torch.nn as nn # nn.CrossEntropyLoss() 和 KLDivLoss 关系 y_pred = torch.tensor([[10.0, 0.0, -10.0], [8.0, 8.0, 8.0]]) y_true = torch.tensor([0, 2]) ce = nn.CrossEntropyLoss(reduction="none")(y_pred, y_true) print(ce) ''' 输出shape是2,tensor([4.5418e-05, 1.0986e+00]) ''' # NLLLoss要求target只能是第几类下标,例如[0,2]表示[label0,label2],转成onehot就是[[1,0,0],[0,0,1]] nll_log_softmax = nn.NLLLoss(reduction="none")(F.log_softmax(y_pred, dim=-1), y_true) print(nll_log_softmax) ''' 输出shape是2,tensor([4.5418e-05, 1.0986e+00]) ''' one_hot = F.one_hot(y_true) #将第几类的下标转换成onehot形式,例如输入[0,2]表示[label0,label2],输出onehot就是[[1,0,0],[0,0,1]] ''' # KLDivLoss要求target为float形式编码,one_hot是longtensor, 所以要one_hot.float();如果是普通的logics,要过一下softmax # KLDivLoss也要求Logits经过LogSoftmax激活。LogSoftmax会把(-inf,inf)的Logits映射到(0,1)再映射到(-inf,0): 当用NLLLoss时,刚好多个负号loss变成(0,inf);当用KLDivLoss时,刚好多个熵。 回顾klLoss的公式 p_i*log(p_i/q_i),其中p_i是(0,1)范围内的targets q_i是将logits映射到(0,1)范围内的结果,所以p_i和q_i都是(0,1)之间 KLDivLoss这个函数的特点就是把log(q_i)这一步扔给输入自己算,这个函数管的只是p_i*log(p_i)-p_i*input NLLLoss这个函数的特点就是把p_i*log(p_i)也没了,只有-p_i*input,所以和LogSoftmax组合起来是CE ''' kl = nn.KLDivLoss(reduction="none")(F.log_softmax(y_pred, dim=-1), one_hot.float()) print(kl) #输出shape是2*3 ''' tensor([[4.5418e-05, 0.0000e+00, 0.0000e+00], [0.0000e+00, 0.0000e+00, 1.0986e+00]]) ''' a = F.softmax(torch.randn(2,3)) print(nn.KLDivLoss(reduction="none")(torch.log(a), a)) ''' 输出是 tensor([[0., 0., 0.], [0., 0., 0.]]) 回顾klLoss的公式 p_i*log(p_i/q_i),其中p_i是(0,1)范围内的targets q_i是将logits映射到(0,1)范围内的结果,所以p_i和q_i都是(0,1)之间 KLDivLoss这个函数的特点就是把log(q_i)这一步扔给输入自己算,这个函数管的只是p_i*log(p_i)-p_i*input NLLLoss这个函数的特点就是把p_i*log(p_i)也没了,只有-p_i*input,所以和LogSoftmax组合起来是CE '''

为什么既有 KL 散度又有交叉熵?在信息论中,熵的意义是对 𝑃 事件的随机变量编码所需的最小字节数,KL 散度的意义是如果我们使用 𝑄的编码来表示 𝑃对应额外所需的编码长度,交叉熵指的是当你使用 𝑄作为密码来表示 𝑃 是所需要的 “平均的编码长度”。但是在机器学习评价两个分布之间的差异时,由于分布 𝑃 会是给定的,所以此时 KL 散度和交叉熵的作用其实是一样的,而且因为交叉熵少算一项,更加简单,所以选择交叉熵会更好。

KL散度和交叉熵在什么条件下是一样的?

不带label smoothing,label是完全的onehot形式(例如3个类,只能是[0,0,1]、[0,1,0]和[1,0,0]),这种情况下KL散度结果就和交叉熵是完全一样的,但是在Pytorch实现中,交叉熵的只能输入其中某一类类别的下标,而Pytorch的KVDivLoss就可以是两个分布算loss,增加了灵活性。KVDivLoss针对 q i q_i qi​也就是logits对应的输入要预先过一下log(都是为了NLLLoss(Softmax)的CrossEntropyLoss进行对齐),而且KVDivLoss和数学上KL(P||Q)的参数顺序是反的,下面截图自 https://pytorch.org/docs/stable/generated/torch.nn.KLDivLoss.html 在这里插入图片描述 稍微总结一下:

CrossEntropyLoss:输入是原始的logits(公式里的Q,对应n个cases×m个类别的矩阵)和labels(公式里的P,对应n个cases所属类别的下标)KVDivLoss:输入是01之间但未过log的logits(公式里的Q,对应n个cases×m个类别的矩阵,当然在01之间,但没进行log)和labels(公式里的P,对应n个cases×m个类别的矩阵,当然在01之间)NLLLoss(LogSoftMax(logits, dim=-1), labels)和CrossEntropyLoss(logits, labels)完全一致,LogSoftMax的输入是原始logits(-无穷到+无穷) Label Smoothing

Label Smoothing是一种防止网络过拟合的手段,在Pytorch的CrossEntropy中已经自带了这个参数,下图截自Hinton的论文When Does Label Smoothing Help? 从公式来看只把我们上面说的label/target做了一个衰减,更多细节可以参考https://blog.csdn.net/taoqick/article/details/121717218 : 在这里插入图片描述

SCE(Symmetric Cross Entropy)和MAE

来自于Symmetric Cross Entropy for Robust Learning with Noisy Labels这篇paper,SCE是CE基础上的一种改进。首先将CE中的pred和label调换顺序,就得到了RCE。再将RCE和CE进行加权,最终得到SCE。SCE的直观想法在于

R C E ( P , Q ) = − ∑ i ∈ [ 0 , n − 1 ] q i l o g p i S C E ( P , Q ) = α C E ( P , Q ) + β R C E ( P , Q ) RCE(P,Q) = -\sum _{i \in[0,n-1]}q_i log p_i \\ SCE(P,Q) = \alpha CE(P,Q) + \beta RCE(P,Q) RCE(P,Q)=−i∈[0,n−1]∑​qi​logpi​SCE(P,Q)=αCE(P,Q)+βRCE(P,Q)

值得注意的是,SCE 并非只有上述 α \alpha α 和 β \beta β两个超参数,上述表达式在求 l o g p i log p_i logpi​ 时,当 p i p_i pi​为0时,当然得对 l o g 0 log 0 log0进行近似,近似的参数在论文中叫做A。当A=-2时,SCE刚好和MAE一样了,对,就是那个|pred-label|求和的MAE。以下摘自Symmetric Cross Entropy for Robust Learning with Noisy Labels: 在这里插入图片描述 对应MAE的定义可以参考论文Robust Loss Functions under Label Noise for Deep Neural Networks,下图中 e j e_j ej​表示第j个样本, u j u_j uj​表示label为1的类对应的softmax后的值。举个例子,例如label=[1,0,0],pred=[0.9,0.05,0.05],那么MAE=2-2*0.9=2,刚好是下图里的MAE公式的表达。还有值得注意的一点是由于是softmax,所以CCE、MAE都可以直接用 u j u_j uj​这样一个最大值表示,但是MSE就不行 在这里插入图片描述 SCE证明是噪声鲁邦的。证明思路在于将loss求期望,下图引用自Generalized Cross Entropy Loss for Training Deep Neural Networks with Noisy Labels 在这里插入图片描述

联合熵

H ( P , Q ) = − ∑ i ∈ [ 0 , n − 1 ] P ( p i , q i ) l o g P ( p i , q i ) H(P,Q)=-\sum _{i \in[0,n-1]}P(p_i,q_i)logP(p_i,q_i) H(P,Q)=−i∈[0,n−1]∑​P(pi​,qi​)logP(pi​,qi​)

条件熵

注意下面 P ( q i ∣ p i ) P(q_i|p_i) P(qi​∣pi​)表示 p i p_i pi​和 q i q_i qi​对应变量的条件概率, P ( p i , q i ) P(p_i,q_i) P(pi​,qi​)表示 p i p_i pi​和 q i q_i qi​对应变量的联合概率,写成这样只是为了简化但不够严谨。 H ( Q ∣ P ) = ∑ i ∈ [ 0 , n − 1 ] p i H ( Q ∣ P = p i ) H ( Q ∣ P ) = − ∑ i ∈ [ 0 , n − 1 ] p i ∗ P ( q i ∣ p i ) l o g P ( q i ∣ p i ) H ( Q ∣ P ) = − ∑ i ∈ [ 0 , n − 1 ] P ( p i , q i ) l o g P ( q i ∣ p i ) H(Q|P)=\sum _{i \in[0,n-1]}p_iH(Q|P=p_i) \\ H(Q|P)=-\sum _{i \in[0,n-1]}p_i*P(q_i|p_i)logP(q_i|p_i) \\ H(Q|P)=-\sum _{i \in[0,n-1]}P(p_i,q_i)logP(q_i|p_i) H(Q∣P)=i∈[0,n−1]∑​pi​H(Q∣P=pi​)H(Q∣P)=−i∈[0,n−1]∑​pi​∗P(qi​∣pi​)logP(qi​∣pi​)H(Q∣P)=−i∈[0,n−1]∑​P(pi​,qi​)logP(qi​∣pi​) 上面就解释了为啥log里面是条件,外面是联合,更进一步地把里面也展开 H ( Q ∣ P ) = − ∑ i ∈ [ 0 , n − 1 ] P ( p i , q i ) l o g P ( q i ∣ p i ) H ( Q ∣ P ) = − H ( P , Q ) − ∑ i ∈ [ 0 , n − 1 ] P ( p i , q i ) l o g P ( p i ) H ( Q ∣ P ) = − H ( P , Q ) + H ( P ) H(Q|P)=-\sum _{i \in[0,n-1]}P(p_i,q_i)logP(q_i|p_i) \\ H(Q|P)=-H(P,Q)-\sum _{i \in[0,n-1]}P(p_i,q_i)logP(p_i) \\ H(Q|P)=-H(P,Q)+H(P) H(Q∣P)=−i∈[0,n−1]∑​P(pi​,qi​)logP(qi​∣pi​)H(Q∣P)=−H(P,Q)−i∈[0,n−1]∑​P(pi​,qi​)logP(pi​)H(Q∣P)=−H(P,Q)+H(P)

​ 至于熵为什么是这个定义请参考 为什么信息熵要定义成 − Σ p ∗ l o g ( p ) -Σp*log(p) −Σp∗log(p)?(https://blog.csdn.net/taoqick/article/details/72852255)。简单来说就是-log§就是信息量,单位用比特表示,例如中国队夺世界杯的信息量远比法国队夺世界杯信息量大。把一个系统里所有的-log§再乘以p就是熵,表示所有信息量加权平均,或者说熵就是信息量的数学期望

还有3个重要结论:

最小化交叉熵和极大似然本质上是一样的,更多推导参考:最小化交叉熵损失与极大似然 - 知乎(https://zhuanlan.zhihu.com/p/51099880)

为什么分类问题用相对熵不用MSE,原因之一是求解时相对熵的梯度下降更快一些,这样可以实现错误越大,下降的越快的效果,更多推导请参考: 分类问题中为什么用交叉熵而不用MSE KL散度和交叉熵的关系_taoqick的专栏-CSDN博客_mse和交叉熵 (https://blog.csdn.net/taoqick/article/details/102621605)

李航老师书里说的最大熵模型是条件熵最大化,想法就是某些知识已经先验知道了,剩下的随机变量尽量等概率随机,这样条件熵最大。学习概率模型时,在满足约束(特征函数)的所有的可能的概率分布中,熵最大的模型就是最大的模型。最大熵模型是判别式模型。

更多推导请参考李航老师的书和数学之美。

​ ​ ​



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭